import math

from flask import current_app, request, session, jsonify

from models import UserActual, HouseInfoFinal


class SimplePagination:
    """Lightweight pagination class compatible with template expectations."""

    def __init__(self, page: int, per_page: int, total: int, items):
        self.page = max(page, 1)
        self.per_page = per_page or 1
        self.total = total
        self.items = items

    @property
    def pages(self):
        if self.per_page == 0:
            return 0
        return math.ceil(self.total / self.per_page)

    @property
    def has_prev(self):
        return self.page > 1

    @property
    def has_next(self):
        return self.page < self.pages

    @property
    def prev_num(self):
        return self.page - 1

    @property
    def next_num(self):
        return self.page + 1

    def iter_pages(self, left_edge=2, left_current=2, right_current=3, right_edge=2):
        last = 0
        for num in range(1, self.pages + 1):
            if num <= left_edge or \
               (self.page - left_current <= num <= self.page + right_current) or \
               num > self.pages - right_edge:
                if last + 1 != num:
                    yield None
                yield num
                last = num


def get_per_page(default=9):
    return current_app.config.get('ITEMS_PER_PAGE', default)


def paginate_list(items, page, per_page):
    total = len(items)
    if per_page <= 0:
        per_page = 1
    pages = max(math.ceil(total / per_page), 1)
    current_page = min(max(page, 1), pages)
    start = (current_page - 1) * per_page
    end = start + per_page
    return SimplePagination(current_page, per_page, total, items[start:end])


def current_user():
    user_id = session.get('user_id')
    if not user_id:
        return None
    return UserActual.query.get(user_id)


def related_houses(target: HouseInfoFinal, limit: int = 3):
    base_query = HouseInfoFinal.query.filter(HouseInfoFinal.id != target.id)
    related = []
    if target.region:
        related = base_query.filter(HouseInfoFinal.region == target.region) \
            .order_by(HouseInfoFinal.publish_time.desc()) \
            .limit(limit) \
            .all()
    if len(related) < limit:
        fallback = base_query.order_by(HouseInfoFinal.publish_time.desc()) \
            .limit(limit - len(related)) \
            .all()
        related.extend(fallback)
    return related


def price_in_range(house, min_price, max_price):
    value = getattr(house, 'price_value', 0) or 0
    if min_price is not None and value < min_price:
        return False
    if max_price is not None and value > max_price:
        return False
    return True


def is_ajax_request():
    return request.headers.get('X-Requested-With') == 'XMLHttpRequest'


def json_response(success: bool, message: str, status: int = 200, **extra):
    payload = {'valid': '1' if success else '0', 'msg': message}
    payload.update(extra)
    return jsonify(payload), status


def first_form_error(form):
    for errors in form.errors.values():
        if errors:
            return errors[0]
    return '提交的数据有误，请检查后再试。'
